
#include <iostream>
#include <fstream>
#include <string.h>
#include "FunctionList.h"

using namespace std;

int main(int argc, char* argv[]) {
  string input_filename;
  string output_filename;      
  string TPprovider;
  if (argc != 4) { 
      std::cout << "Usage is: augment-traces <infile> <outfile> TPprovider_name \n";
      exit(0);
  } else { 
      input_filename = argv[1];
      output_filename = argv[2];
      std::string s(argv[3]);
      TPprovider = s;
  }
  
  
  
  // Check if input file exists
  std::ifstream f_ex(input_filename.c_str());
  bool file_exists = f_ex.good();
  f_ex.close();
  if (!file_exists) {
     cout << "Error: input file does not exist" << endl;
     exit(0);
  }
  
  // Read the traces in the input_filename. 
  /* The format of these traces is:
         P0  @ 0000000001519558 => mytps/main__in { }
     without headers but an empty line!
  */     
  const int MAX_CHARS_PER_LINE = 512;
  const int TOKENS_PER_LINE = 7;
  const char* DELIMITER = (const char*) " ";
  
  // open the file
  std::ifstream fin;
  fin.open(input_filename.c_str(), std::ifstream::in);
  
  // read and drop the empty line
  if (!fin.eof()) {
     char buf[MAX_CHARS_PER_LINE];
     fin.getline(buf, MAX_CHARS_PER_LINE);
  }
   
  FunctionList* templist = new FunctionList();
  FunctionList* sortedlist = new FunctionList();
  
  // Loop for each row in the file
  while (!fin.eof()) {
        
           // read an entire line/row into memory
           char buf[MAX_CHARS_PER_LINE];
           fin.getline(buf, MAX_CHARS_PER_LINE);
  
           // array to store memory addresses of the tokens in buf
           const char* token[TOKENS_PER_LINE] = {}; // initialize to 0

           // parse the line into blank-delimited tokens
           token[0] = strtok(buf, DELIMITER); // first token
           for (int i = 1; i < TOKENS_PER_LINE; i++) {
               token[i] = strtok(0, DELIMITER); // subsequent tokens
           }
                                   
           // convert the data read into function parameters
           string fct_fullname (token[4]);
//cout << fct_fullname << endl;
           
           string type = fct_fullname.substr(fct_fullname.length()-3, 3);                   
//cout << type << endl;

           string fct_name;
           int fct_type;
           int str_comparison = strcmp(type.c_str(), "_in");
           if (str_comparison == 0) fct_type = 1;
           else {
                str_comparison = strcmp(type.c_str(), "out");
                if (str_comparison == 0) fct_type = 2;
                else {
                     cout << "PROBLEM!" << endl;
                     fct_type = 3;
                }
           }
//cout << fct_type << endl;
                      
           if (fct_type == 1) fct_name = fct_fullname.substr(TPprovider.length()+1, fct_fullname.length() - 1 - TPprovider.length() - 4);
           else if (fct_type == 2) fct_name = fct_fullname.substr(TPprovider.length()+1, fct_fullname.length() - 1 - TPprovider.length() - 5);           
//cout << fct_name << endl;
           
           long cycle = std::atol(token[2]);           
//cout << cycle << endl;
            
           if (fct_type == 1) {
              Function* fct = new Function(fct_name, cycle, 0);
              templist->addFront(fct);
//cout << "Added to the templist" << endl;
//             templist->print();
           }
           if (fct_type == 2) {
              Function* fct = templist->getAndPop(fct_name);
              fct->EndCycle = cycle;
              sortedlist->addFront(fct);
//cout << "Added to the SORTED list" << endl;
//              sortedlist->print();
              }           
    }
    
    fin.close();
    
  // Save the function in the right format

  ofstream myfile;
  myfile.open(output_filename.c_str());  
  myfile << "#CYCLE\tEND_CYCLE\tTRACE_NAME\tFUNCTION\n";
  for (Function* f = sortedlist->getFirstFunction(); f; f = sortedlist->getNextFunction()) {
      myfile << f->StartCycle << "\t" << f->EndCycle << "\t" << "trace_name" << "\t" << f->FunctionName << endl;
  }
  myfile.close();

  return 0;
}
